<?php
/**
 * Handler Socket Class to handle socket nosql connect to mysql
 *
 * @package SGN
 * @version $Id$
 * @author $Author: tamlt2 $
 *
 */
class SGN_HandlerSocket extends HandlerSocket
{
    /**
     * $handlerClient
     * Handler Client
     * For manager all Socket Client
     */
    static $handlerClient;
    private $_profilerData = array();
    private $_connectionName = '';
    /**
     * Creates a new conection objects.
     * 
     * @param string $host
     * @param string $port
     * @param array $options
     * 
     * @return HandlerSocket
     */
    public function __construct($host, $port, $options = array())
    {
        $this->_connectionName = $host . '_' . $port;
        return parent::__construct($host, $port, $options);
    }
    /**
     * Authenticate using a plain password.
     * 
     * @param string $key
     * @param string $type
     * 
     * @return boolean
     * 
     */
    public function auth($key, $type = '')
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::auth($key, $type);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::auth($key, $type);
    }
    /**
     * 
     * @param long $id
     * @param string $operate
     * @param array $criteria
     * @param long $limit
     * @param long $offset
     * @param string $update
     * @param array $values
     * @param array $filters
     * @param long $in_key
     * @param array $in_values
     * 
     * @return mixed
     * 
     */
    public function executeSingle($id, $operate, $criteria, $limit = 1, $offset = 0, $update = null, $values = array(), $filters = array(), $in_key = -1, $in_values = array()) 
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::executeSingle($id, $operate, $criteria, $limit, $offset, $update, $values, $filters, $in_key, $in_values);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::executeSingle($id, $operate, $criteria, $limit, $offset, $update, $values, $filters, $in_key, $in_values);
    }
    /**
     * Execute
     * 
     * @param array $args
     * 
     * @return mixed
     */
    public function executeMulti($args)
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::executeMulti($args);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::executeMulti($args);
    }
    /**
     * Update
     * 
     * @param integer $id
     * @param string $operate
     * @param array $criteria
     * @param array $values
     * @param integer $limit
     * @param integer $offset
     * @param array $filters
     * @param integer $in_key
     * @param array $in_values
     * 
     * @return mixed
     */
    public function executeUpdate($id, $operate, $criteria, $values, $limit = 1, $offset = 0, $filters = array(), $in_key = -1, $in_values = array())
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::executeUpdate($id, $operate, $criteria, $values, $limit, $offset, $filters, $in_key, $in_values);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::executeUpdate($id, $operate, $criteria, $values, $limit, $offset, $filters, $in_key, $in_values);
    }
    /**
     * Delete
     * 
     * @param integer $id
     * @param string $operate
     * @param array $criteria
     * @param integer $limit
     * @param integer $offset
     * @param array $filters
     * @param integer $in_key
     * @param array $in_values
     * 
     * @return mixed
     */
    public function executeDelete($id, $operate, $criteria, $limit = 1, $offset = 0, $filters = array(), $in_key = -1, $in_values = array())
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::executeDelete($id, $operate, $criteria, $limit, $offset, $filters, $in_key, $in_values);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::executeDelete($id, $operate, $criteria, $limit, $offset, $filters, $in_key, $in_values);
    }
    /**
     * Insert
     * 
     * @param integer $id
     * @param array $field
     * 
     * @return mixed
     */
    public function executeInsert($id, $field)
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::executeInsert($id, $field);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData($this->_connectionName, $this->_profilerData, 'HandlerSocket');
            return $result;
        }
        return parent::executeInsert($id, $field);
    }
    /**
     * Get a last error message
     * 
     * @return string Returns the error message.
     */
    public function getError()
    {
        return parent::getError();
    }
    /**
     * Creates a new index objects
     * 
     * @param integer $id
     * @param string $db
     * @param string $table
     * @param string $index
     * @param string|array $fields
     * @param array $options
     * 
     * @return andlerSocketIndex
     */
    public function createIndex($id, $db, $table, $index, $fields, $options = array())
    {
        if (SGN_Application::isRegistered('profiler')) {
            $_startTime = microtime(true);
            $result = parent::createIndex($id, $db, $table, $index, $fields, $options);
            // profiling
            $this->_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $this->_profilerData['method'] = __METHOD__;
            $this->_profilerData['args'] = func_get_args();
            SGN_Application::get('profiler')->setProfilerData('HandlerSocket', $this->_profilerData, $this->_connectionName);
            return $result;
        }
        return parent::createIndex($id, $db, $table, $index, $fields, $options);
    }
    /**
     * getSocket
     * Get Handler Socket for connect SQL
     * @param $options Connection information
     * @param $openIndex Index of Connection
     * @return HandlerSocket Object
     */
    static function getSocket($options, $openIndex = 0)
    {
        /**
         * Check Connection Input
         */
        if (!isset($options->host) || !isset($options->port) || !isset($options->database) 
                || !isset($options->table) || !isset($options->keyindex) || !isset($options->columns)) {
            // throw Exception
            $message = "Miss param connection: ".serialize($options);
            SGN_Log::writeLog(__CLASS__, __FUNCTION__ . 'Error: '.$message, date('H:i:s d-m', time()) . ' - error: not found extension');
            throw new Exception($message);
        }
        /**
         * Open Index Connection
         */
        if (empty($openIndex) && isset($options->openIndex)) {
            $openIndex = $options->openIndex;
        }
        /**
         * Init Config
         * Return if exit instance
         */
        $config = array('host' => $options->host, 'port' => $options->port, 'database' => $options->database,
                        'table' => $options->table, 'keyindex' => $options->keyindex, 'columns' => $options->columns,
                        'openIndex' => $openIndex);
        $handlerClientKey = serialize($config);
        if (self::$handlerClient[$handlerClientKey]) {
            return self::$handlerClient[$handlerClientKey];
        }
        /**
         * Check library exist
         */
        if (!extension_loaded('handlersocket') || !class_exists('HandlerSocket')) {
            // Write Log
            $ipServer = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '';
            SGN_Log::writeLog(__CLASS__, __FUNCTION__ . 'Error', date('H:i:s d-m', time()) . ' - error: not found extension in '. $ipServer);
            // throw Exception
            throw new Exception("Module handlersocket not found in ".__CLASS__." $ipServer");
        }
        $_startTime = microtime(true);
        /**
         * Open Socket
         */
        $handlerSocket = new SGN_HandlerSocket($options->host, $options->port);
        if (!($handlerSocket->openIndex($openIndex, $options->database, $options->table, $options->keyindex, $options->columns))) {
            // Write Log
            SGN_Log::writeLog(__CLASS__, __FUNCTION__ . 'Error', date('H:i:s d-m', time()) . ' - error: '.$handlerSocket->getError());
            // throw Exception
            throw new Exception("Handler Socket Error ".$handlerSocket->getError());
        }
        // Cache Object
        self::$handlerClient[$handlerClientKey] = $handlerSocket;
        if (SGN_Application::isRegistered('profiler')) {
            // profiling
            $_profilerData['totalTime'] = sprintf("%1.3f", (microtime(true) - $_startTime) * 1000); // in miliseconds
            $_profilerData['method'] = __METHOD__;
            $_profilerData['args'] = array($options->host, $options->port);
            SGN_Application::get('profiler')->setProfilerData($options->host . "_" . $options->port, $_profilerData, 'HandlerSocket');
        }
        return $handlerSocket;
    }
}